package edu.server.dominio;

import java.util.LinkedList;
import java.util.List;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;

import edu.server.repositorio.Proveedor;
import edu.server.repositorio.RenglonOrdenCompraProducto;
import edu.server.repositorio.RequerimientoCompra;
import edu.server.util.HibernateUtil;


public class D_RequerimientoCompra {
	
	public D_RequerimientoCompra()
	{
	}
	
	/**
	 * Método que busca en la base de datos los requerimientos de compra de productos que provee el proveedor pasado como parámetro.
	 * @param proveedor. Proveedor que provee el producto del requerimiento de compra.
	 * @return List<RequerimientoCompra>. Retorna una lista con los requerimientos de compra que pueden ser satisfechos por el proveedor.
	 */
	@SuppressWarnings("unchecked")
	public List<RequerimientoCompra> buscarPorProveedor(Proveedor proveedor)
	{
		List<RequerimientoCompra> requerimientosCompra;
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		String hql = "SELECT rc" +
					" FROM RequerimientoCompra rc, RequerimientoMateriales rm, ProveedorDeProducto pdp" +
					" WHERE rc.requerimientoMateriales.idRequerimientoMateriales = rm.idRequerimientoMateriales" +
					" AND pdp.producto.idProducto = rm.producto.idProducto" +
					" AND rc.renglonOrdenCompraProducto IS NULL";
		
		if(proveedor != null)
			hql = hql + " AND pdp.proveedor.codigoProveedor = " + proveedor.getCodigoProveedor();
		
		requerimientosCompra = session.createQuery(hql).list();
		
		for(RequerimientoCompra requerimiento : requerimientosCompra)
		{
			Hibernate.initialize(requerimiento.getRequerimientoMateriales());
			Hibernate.initialize(requerimiento.getRequerimientoMateriales().getProducto());
			Hibernate.initialize(requerimiento.getRequerimientoMateriales().getProducto().getElementoProducto());
			Hibernate.initialize(requerimiento.getRequerimientoMateriales().getProducto().getMaterialProducto());
			Hibernate.initialize(requerimiento.getRequerimientoMateriales().getProducto().getMedidaFijaProducto());
		}
				
		session.close();
		
		return requerimientosCompra;
	}
	
	
	/**
	 * Método que busca en la base de datos todos los requerimientos de compra vinculados al renglon que tiene el id pasado como parámetro
	 * @param idRenglon. Id del renglón para el cual se buscan los requerimientos vinculados.
	 * @return List<RequerimientoCompra>. Retorna una lista con los requerimientos de compra vinculados al renglon que tiene como id el
	 * pasado como parámetro.
	 */
	@SuppressWarnings("unchecked")
	public List<RequerimientoCompra> buscarPorRenglonOrdenCompra(int idRenglon)
	{
		List<RequerimientoCompra> requerimientos;
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		String hql = "from RequerimientoCompra " +
					 "where renglonOrdenCompraProducto.idRenglonOrdenCompraProducto = " + idRenglon;
		
		requerimientos = session.createQuery(hql).list();
		
		for(RequerimientoCompra requerimiento : requerimientos)
		{
			Hibernate.initialize(requerimiento.getRequerimientoMateriales());
			Hibernate.initialize(requerimiento.getRequerimientoMateriales().getProducto());
			Hibernate.initialize(requerimiento.getRequerimientoMateriales().getProducto().getElementoProducto());
			Hibernate.initialize(requerimiento.getRequerimientoMateriales().getProducto().getMaterialProducto());
			Hibernate.initialize(requerimiento.getRequerimientoMateriales().getProducto().getMedidaFijaProducto());			
		}
		
		session.close();
		
		return requerimientos;
	}
	
	/**
	 * Método que asigna la orden de compra a los requerimientos de compra que tiene los id pasados como parámetros.
	 * @param idRequerimientos. Id de los requerimientos de compra que hay que setearle la orden de compra.
	 * @param idOrdenCompra. Id de la orden de compra que se seteará a los requerimientos de compra.
	 */
	public void asignarRenglonOrdenCompraProducto(List<List<Integer>> idRequerimientos, List<RenglonOrdenCompraProducto> renglones) throws Exception
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try{
			session.beginTransaction();
							
			//por cada renglón mapeado...
			for(int i=0; i<idRequerimientos.size(); i++)
			{	
				RenglonOrdenCompraProducto renglon = renglones.get(i);
				
				//obtenemos los ids que conforman ese renglón. Pueden ser varios por el algoritmo de mapeo realizado
				List<Integer> listaIds = idRequerimientos.get(i);
				
				//por cada id de la lista...
				for(int j=0; j<listaIds.size(); j++)
				{
					//obtenemos el requerimiento que repesenta ese id y le seteamos el renglón de la orden de compra de producto
					RequerimientoCompra requerimiento = (RequerimientoCompra) session.get(RequerimientoCompra.class, listaIds.get(j));
					
					//el requirimiento será nulo cuando el renglón esté relacionado a un requerimiento adicional
					requerimiento.setRenglonOrdenCompraProducto(renglon);
										
					//actualizamos los datos del requerimiento en la base de datos
					session.saveOrUpdate(requerimiento);
				}
			}
			
			session.getTransaction().commit();
		}
		
		catch(HibernateException he)
		{
			session.getTransaction().rollback();
			throw he;
		}
		
		catch(Exception e)
		{
			session.getTransaction().rollback();
			throw new Exception("Se produjo un error al intentar actualizar los requerimientos de compra.");
		}
	}
	
	
	/**
	 * Método que borra los requerimientos de compra relacionados a un renglon de la orden de compra.
	 * @param idRenglonOrdenCompra. Id del renglon de la orden de compra.
	 */
	@SuppressWarnings("unchecked")
	public void borrar(int idRenglonOrdenCompra)
	{
		List<RequerimientoCompra> requerimientos = new LinkedList<RequerimientoCompra>();
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try
		{
			session.beginTransaction();
			
			//buscamos todos los requerimientos de compra que tengan como renglon el pasado como parámetro
			String hql = "from RequerimientoCompra" +
					     " where renglonOrdenCompraProducto.idRenglonOrdenCompraProducto = " + idRenglonOrdenCompra;
			
			requerimientos = session.createQuery(hql).list();
			
			//eliminamos cada uno de los requerimientos
			for(RequerimientoCompra requerimiento : requerimientos)
				session.delete(requerimiento);
			
			session.getTransaction().commit();
		}
			
		catch(HibernateException he)
		{
			session.getTransaction().rollback();
			
			throw he;
		}
	}
	
	/**
	 * Método que cambia la propiedad "activo" de un requerimiento de compra según el renglón de orden de compra al que está asociado.
	 * @param idRenglonOrden. Renglón de la orden de compra.
	 * @param activo. Valor que tomará el bit activo (true o false).
	 */
	public void setActivo(int idRenglonOrden, boolean activo)
	{		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try{
			session.beginTransaction();
			
			String hql = "update RequerimientoCompra " +
						 "set activo = '" + activo + "' " +
						 "where renglonOrdenCompraProducto.idRenglonOrdenCompraProducto = " + idRenglonOrden;
					
			session.createQuery(hql).executeUpdate();
			
			session.getTransaction().commit();
		}
		
		catch(HibernateException he){
			session.getTransaction().rollback();
			
			throw he;
		}
	}
	
	/**
	 * Método que desvincula el renglón de la orden de compra de producto al requerimiento de material
	 * @param idRenglonOrden. Rengón de la orden de compra de producto
	 */
	public void desvincularRenglonOrdenCompraProducto(int idRenglonOrden)
	{		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try{
			session.beginTransaction();
			
			String hql = "update RequerimientoCompra " +
						 "set renglonOrdenCompraProducto = NULL " +
						 "where renglonOrdenCompraProducto.idRenglonOrdenCompraProducto = " + idRenglonOrden;
					
			session.createQuery(hql).executeUpdate();
			
			session.getTransaction().commit();
		}
		
		catch(HibernateException he){
			session.getTransaction().rollback();
			
			throw he;
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<RequerimientoCompra> buscarPorOrdenFabricacion(int nroOrdenFabricacion)
	{
		List<RequerimientoCompra> requerimientos;
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		String hql = "SELECT rc " +
					 "FROM RequerimientoCompra rc " + 
					 "WHERE rc.requerimientoMateriales.ordenFabricacionGeneral.nroOrden = " + nroOrdenFabricacion;
		
		requerimientos = session.createQuery(hql).list();
		
		session.close();
		
		return requerimientos;
	}
	
	public void borrar(List<RequerimientoCompra> requerimientos)
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try{
			session.beginTransaction();
			
			for(RequerimientoCompra requerimiento : requerimientos)
			{
				requerimiento.setActivo(false);
				session.saveOrUpdate(requerimiento);
			}
			
			session.getTransaction().commit();
		}
		
		catch(HibernateException he){
			session.getTransaction().rollback();
			throw he;
		}
	}
}
